#include "StdAfx.h"
#include "StreamingSounddx.h"

#include <iostream>

namespace directx{

StreamingSounddx::StreamingSounddx(const char* _fileName, LPDIRECTSOUNDBUFFER8 _buf, DWORD _bufferSize)
{
	fileName = _fileName;
	m_lpSB = _buf;
	bufferSize = _bufferSize;
	isPlaying = false;
	
}

StreamingSounddx::StreamingSounddx(void)
{
}

StreamingSounddx::~StreamingSounddx(void)
{
}

void StreamingSounddx::destroy(){

	DELETE_POINTER(fileName);
	RELEASE(m_lpSB);
	CloseHandle(hBufferThread);
}	

DWORD WINAPI FillBuffer(LPVOID lpParam){	 

	StreamingSounddx* sndObj = (StreamingSounddx*) lpParam;
	DWORD halfSize = (sndObj->getBufferSize())/2;
	LPDIRECTSOUNDBUFFER8 lpSB = sndObj->getSoundBuffer();	
	DWORD position;
	int coin = 2;
	
	////////////////////////////////////////////////////////////////
	// Excess SoundFile
	////////////////////////////////////////////////////////////////	
	HMMIO m_hmmio;	
	LPSTR strFileName = (char*) sndObj->getFileName();

	m_hmmio = mmioOpen( strFileName, NULL, MMIO_READ );

	if(!m_hmmio)
	{
		coreGetLog()->WriteError("mmioOpen failed! Can't open: "+*strFileName, __FILE__, __LINE__);
		return false;
	}
	
	MMCKINFO mmWave;
	MMCKINFO mmData;
	
	ZeroMemory(&mmWave, sizeof(mmWave));
	ZeroMemory(&mmData, sizeof(mmData));
	HRESULT mResult = 0;	

	// find the WAVE chunk
	mmWave.fccType = mmioStringToFOURCC("WAVE", 0);
	mmData.ckid = mmioStringToFOURCC("data", 0);
	mResult = mmioDescend(m_hmmio, &mmWave, NULL, MMIO_FINDRIFF);
	if(mResult != MMSYSERR_NOERROR)
	{
		coreGetLog()->WriteError("mmioDescend failed. ", __FILE__, __LINE__);
		return FALSE;
	}

	// find the data chunk
	mResult = mmioDescend(m_hmmio, &mmData, &mmWave, MMIO_FINDCHUNK);
	if(mResult != MMSYSERR_NOERROR)
	{
		coreGetLog()->WriteError("mmioDescend failed. ", __FILE__, __LINE__);
		return FALSE;
	}	
	
	while(sndObj->getIsPlaying()){
		lpSB->GetCurrentPosition(&position, NULL);
		switch(coin){
			case 1:
				if(position>halfSize){
					LPVOID lpvWrite;
					DWORD  dwLength;
					
					if (DS_OK == lpSB->Lock(
						0,			// Offset at which to start lock.
						halfSize,   // Size of lock; ignored because of flag.
						&lpvWrite,  // Gets address of first part of lock.
						&dwLength,  // Gets size of first part of lock.
						NULL,       // Address of wraparound not needed. 
						NULL,       // Size of wraparound not needed.
						0))			// Flag.
						{
							mResult = mmioRead(m_hmmio, (HPSTR)lpvWrite, dwLength);	
							if(mResult == -1)
							{
								coreGetLog()->WriteError("Error reading wavedata. ", __FILE__, __LINE__);
								return false;
							}
							lpSB->Unlock(
								lpvWrite,   // Address of lock start.
								dwLength,   // Size of lock.
								NULL,       // No wraparound portion.
								0);
						}else{
							coreGetLog()->WriteError("Could lock buffer. ", __FILE__, __LINE__);					
						}				
					coin = 2;
				}
				break;

			case 2:
				if(position<halfSize){
					LPVOID lpvWrite;
					DWORD  dwLength;
					
					if (DS_OK == lpSB->Lock(
						halfSize,   // Offset at which to start lock.
						halfSize,   // Size of lock; ignored because of flag.
						&lpvWrite,  // Gets address of first part of lock.
						&dwLength,  // Gets size of first part of lock.
						NULL,       // Address of wraparound not needed. 
						NULL,       // Size of wraparound not needed.
						0))			// Flag.
						{
							mResult = mmioRead(m_hmmio, (HPSTR)lpvWrite, dwLength);	
							if(mResult == -1)
							{
								coreGetLog()->WriteError("Error reading wavedata. ", __FILE__, __LINE__);
								return false;
							}								
							lpSB->Unlock(
								lpvWrite,   // Address of lock start.
								dwLength,   // Size of lock.
								NULL,       // No wraparound portion.
								0);
						}else{
							coreGetLog()->WriteError("Could lock buffer. ", __FILE__, __LINE__);					
						}
					coin = 1;
				}
				break;
		}		
		Sleep(500);
	}
	mmioClose(m_hmmio,0);
	return 0;
}

bool StreamingSounddx::getIsPlaying(){
	return isPlaying;
}

const char* StreamingSounddx::getFileName(){
	return fileName;
}

LPDIRECTSOUNDBUFFER8 StreamingSounddx::getSoundBuffer(){
	return m_lpSB;
}

DWORD StreamingSounddx::getBufferSize(){
	return bufferSize;
}

bool StreamingSounddx::play(){
	
	if(!isPlaying){
	
		isPlaying=true;
		
		hBufferThread = CreateThread(NULL, 0, 
				(LPTHREAD_START_ROUTINE) FillBuffer, 
				this,  // pass event handle
				0, NULL); 
	    
		if (hBufferThread == NULL){
			coreGetLog()->WriteError("Couldn't create BufferThread ", __FILE__, __LINE__);
			return false;
		}

		m_lpSB->Play(0,0,DSBPLAY_LOOPING);
	}

	return true;
}



bool StreamingSounddx::stop(){
	m_lpSB->Stop();
	isPlaying=false;
	return true;
}

bool StreamingSounddx::setVolume(int _v){
	return true;
}


}